//
//  XLFormRowDescriptor.h
//  XLForm ( https://github.com/xmartlabs/XLForm )
//
//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.


#import <Foundation/Foundation.h>
#import "XLFormBaseCell.h"
#import "XLFormValidatorProtocol.h"
#import "XLFormValidationStatus.h"

extern CGFloat XLFormUnspecifiedCellHeight;

@class XLFormViewController;
@class XLFormSectionDescriptor;
@protocol XLFormValidatorProtocol;
@class XLFormAction;
@class XLFormBaseCell;

typedef NS_ENUM(NSUInteger, XLFormPresentationMode) {
    XLFormPresentationModeDefault = 0,
    XLFormPresentationModePush,
    XLFormPresentationModePresent
};

NS_ASSUME_NONNULL_BEGIN

typedef void(^XLOnChangeBlock)(id __nullable oldValue,id __nullable newValue,XLFormRowDescriptor * rowDescriptor);

@interface XLFormRowDescriptor : NSObject
@property (strong, nonatomic, nullable) id cellClass;
@property (readwrite, nullable) NSString * tag;
@property (strong, nonatomic, readonly, nonnull) NSString *rowType;
@property (strong, nonatomic, nullable) NSString * title;
/** cell model type，默认0,对应 XZApprovalFormCellModel.type */
@property (assign, nonatomic) NSInteger cellType;
/** 结果值，一般是用户输入、选择、填写的内容 */
@property (strong, nonatomic, nullable) id value;
/** value 为空的block，默认nil，一般也就是value = nil;有些情况value是个对象，是否为空根据value的某个字段判断 */
@property (copy, nonatomic) BOOL (^ _Nullable valueEmptyBlock)(id _Nullable value);

/** 选择的callback，需要各自的cell主动触发，这里只提供通知的通道（和action.formBlock不一样，它是由系统触发）。默认nil，适用于操作cell里的按钮之后，通知界面 */
@property (copy, nonatomic) void(^ _Nullable selectCallback)(XLFormRowDescriptor *descriptor, id _Nullable extData);
/** 重新加载的callback，需要各自的cell主动触发，这里只提供通知的通道 ，默认nil，适用于操作cell完成（输入完成、选择完成）之后，通知界面刷新 */
@property (copy, nonatomic) void(^ _Nullable reloadCallback)(XLFormRowDescriptor *descriptor);

/** 父的rowType,默认nil;自定义的cell，有自己的rowType,FormSDK需要判断某个类型的rowType，来处理一些事情 */
@property (strong, nonatomic, nullable) NSString *superRowType;
@property (strong, nonatomic, nullable) Class valueTransformer;
/** value 的格式化函数，默认nil */
@property (copy, nonatomic, nullable) NSString *(^valueTransformerBlock)(XLFormRowDescriptor * descriptor);
/// value item格式化，适合value是对象数组的情况
@property (copy, nonatomic, nullable) NSString *(^valueItemTransformerBlock)(id valueItem);

//MARK: - 公共
/// cell 高度
@property (nonatomic) CGFloat height;
/// cell style
@property UITableViewCellStyle cellStyle;
/// icon图片，默认nil，不设置
@property (nonatomic, strong, nullable) UIImage *iconImage;
/// 自定义指示器图片，（默认nil，则根据accessoryType来显示）
@property (nonatomic, strong, nullable) UIImage *indicatorImage;
/** cell.accessoryType, 默认nil, 见枚举 UITableViewCellAccessoryType  */
@property (nonatomic, strong, nullable) NSNumber *accessoryType;
///cell 背景色，默认nil，不设置
@property (nonatomic, strong, nullable) UIColor *bgColor;
///contentView 背景色，默认nil，不设置
@property (nonatomic, strong, nullable) UIColor *contentBgColor;
/// 分割线left，默认0，不设置，如果小于0，则不显示
@property (nonatomic, assign) CGFloat splitLeft;
/// 扩展数据
@property (nonatomic, strong, nullable) NSDictionary<NSString *, id> *extData;
/** 外层附加状态 */
@property (assign, nonatomic) NSInteger status;
//MARK: - 圆角边框
/// 圆角，默认0，不显示圆角
@property (nonatomic, assign) CGFloat cornerRadius;
/// 圆角内边距，默认{0,0,0,0},
@property (nonatomic, assign) UIEdgeInsets cornerInsets;
/// 边框颜色，默认nil
@property (nonatomic, strong, nullable) UIColor *borderColor;
/// 边框粗细，默认0
@property (nonatomic, assign) CGFloat borderWidth;
/// 圆角内部背景色，默认白色
@property (nonatomic, assign, nullable) UIColor *cornerInnerBgColor;


//MARK: - lable
/** title lb left，默认0，cell 内部自己调整 */
@property (nonatomic, assign) float titleLeft;
/** title lb 宽度，默认0，cell 内部自己调整 */
@property (nonatomic, assign) float titleWidth;
/** title lb 字体，默认nil */
@property (nonatomic, strong, nullable) UIFont *titleFont;
/** title lb 颜色，默认nil */
@property (nonatomic, strong, nullable) UIColor *titleColor;
/** title lb textAlignment，默认 left */
@property (nonatomic, assign) NSTextAlignment titleAlignment;
/** detail lb 字体，默认nil */
@property (nonatomic, strong, nullable) UIFont *detailFont;
/** detail lb 颜色，默认nil */
@property (nonatomic, strong, nullable) UIColor *detailColor;
/** detail lb textAlignment，默认 left */
@property (nonatomic, assign) NSTextAlignment detailAlignment;

//MARK: - 输入框
/** 单位，显示在输入框后面，和textField.placeholder 不一样，这个是固定展示的，默认nil */
@property (nonatomic, strong, nullable) NSString *unit;
/** text 字体，默认nil */
@property (nonatomic, strong, nullable) UIFont *textFont;
/** text  颜色，默认nil */
@property (nonatomic, strong, nullable) UIColor *textColor;
/** text 的占位符，默认nil */
@property (nonatomic, strong, nullable) NSString *textPlaceholder;
/** text textAlignment，默认 nil */
@property (nonatomic, strong, nullable) NSNumber *textAlignment;
/** text left，默认0，表示：label.right+30 */
@property (nonatomic, assign) CGFloat textLeft;
/** text 最大输入长度，默认0，不限制 */
@property (nonatomic, assign) NSInteger textMaxLength;

//MARK: - 日期
/// 时间格式,默认nil,只针对 时间cell
@property (nonatomic, strong, nullable) NSString *dateFromater;
/// 默认选择的日期，默认nil
@property (nonatomic, strong, nullable) NSDate *defaultDate;
/// 最大日期，默认nil
@property (nonatomic, strong, nullable) NSDate *maxDate;
/// 最小日期，默认nil
@property (nonatomic, strong, nullable) NSDate *minDate;

//MARK: - 附件
/** 最大附件数量，默认 9 */
@property (nonatomic, assign) NSInteger maxPhotoCount;

@property (nonatomic, copy, nullable) XLOnChangeBlock onChangeBlock;
@property BOOL useValueFormatterDuringInput;
@property (nonatomic, nullable) NSFormatter *valueFormatter;

//MARK: - cell config
@property (nonatomic, readonly, nonnull) NSMutableDictionary * cellConfig;
@property (nonatomic, readonly, nonnull) NSMutableDictionary * cellConfigForSelector;
@property (nonatomic, readonly, nonnull) NSMutableDictionary * cellConfigIfDisabled;
@property (nonatomic, readonly, nonnull) NSMutableDictionary * cellConfigAtConfigure;
@property (nonnull) id disabled;
-(BOOL)isDisabled;
@property (nonnull) id hidden;
-(BOOL)isHidden;
@property (getter=isRequired) BOOL required;
@property (nonnull) XLFormAction * action;
@property (weak, null_unspecified) XLFormSectionDescriptor * sectionDescriptor;

//MARK: - 构造方法
+(nonnull instancetype)formRowDescriptorWithTag:(nullable NSString *)tag rowType:(nonnull NSString *)rowType;
+(nonnull instancetype)formRowDescriptorWithTag:(nullable NSString *)tag rowType:(nonnull NSString *)rowType title:(nullable NSString *)title;
-(nonnull instancetype)initWithTag:(nullable NSString *)tag rowType:(nonnull NSString *)rowType title:(nullable NSString *)title;
-(nonnull XLFormBaseCell *)cellForFormController:(nonnull XLFormViewController *)formController;

@property (nullable) NSString *requireMsg;
-(void)addValidator:(nonnull id<XLFormValidatorProtocol>)validator;
-(void)removeValidator:(nonnull id<XLFormValidatorProtocol>)validator;
-(nullable XLFormValidationStatus *)doValidation;


//MARK: - helper
/// returns the display text for the row descriptor, taking into account NSFormatters and default placeholder values
- (NSString *_Nullable) displayTextValue;

/// returns the editing text value for the row descriptor, taking into account NSFormatters.
- (NSString *_Nullable) editTextValue;

/**
 判断 rowValue 是否为空
 
 @param rowValue rowValue description
 @return return value description
 */
+ (BOOL)xl_rowValueIsEmpty:(id _Nullable )rowValue;

// ===========================
// property used for Selectors
// ===========================
@property (nullable) NSString * noValueDisplayText;
@property (nullable) NSString * selectorTitle;
@property (nullable) NSArray * selectorOptions;

@property (null_unspecified) id leftRightSelectorLeftOptionSelected;


// =====================================
// Deprecated
// =====================================
@property (null_unspecified) Class buttonViewController DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("Use action.viewControllerClass instead");
@property XLFormPresentationMode buttonViewControllerPresentationMode DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("use action.viewControllerPresentationMode instead");
@property (null_unspecified) Class selectorControllerClass DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("Use action.viewControllerClass instead");


@end

typedef NS_ENUM(NSUInteger, XLFormLeftRightSelectorOptionLeftValueChangePolicy)
{
    XLFormLeftRightSelectorOptionLeftValueChangePolicyNullifyRightValue = 0,
    XLFormLeftRightSelectorOptionLeftValueChangePolicyChooseFirstOption,
    XLFormLeftRightSelectorOptionLeftValueChangePolicyChooseLastOption
};


// =====================================
// helper object used for LEFTRIGHTSelector Descriptor
// =====================================
@interface XLFormLeftRightSelectorOption : NSObject

@property (nonatomic, assign) XLFormLeftRightSelectorOptionLeftValueChangePolicy leftValueChangePolicy;
@property (readonly, nonnull) id leftValue;
@property (readonly, nonnull) NSArray *  rightOptions;
@property (readonly, null_unspecified) NSString * httpParameterKey;
@property (nullable) Class rightSelectorControllerClass;

@property (nullable) NSString * noValueDisplayText;
@property (nullable) NSString * selectorTitle;


+(nonnull XLFormLeftRightSelectorOption *)formLeftRightSelectorOptionWithLeftValue:(nonnull id)leftValue
                                                          httpParameterKey:(null_unspecified NSString *)httpParameterKey
                                                              rightOptions:(nonnull NSArray *)rightOptions;


@end


@protocol XLFormOptionObject

@required

-(nonnull NSString *)formDisplayText;
-(nonnull id)formValue;

@end

@interface XLFormAction : NSObject

@property (nullable, nonatomic, strong) Class viewControllerClass;
@property (nullable, nonatomic, strong) NSString * viewControllerStoryboardId;
@property (nullable, nonatomic, strong) NSString * viewControllerNibName;

@property (nonatomic) XLFormPresentationMode viewControllerPresentationMode;

@property (nullable, nonatomic, strong) void (^formBlock)(XLFormRowDescriptor * __nonnull sender);
@property (nullable, nonatomic, strong) void (^otherBlock)(XLFormRowDescriptor * __nonnull sender, id __nullable data);
@property (nullable, nonatomic) SEL formSelector;
@property (nullable, nonatomic, strong) NSString * formSegueIdenfifier DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("Use formSegueIdentifier instead");
@property (nullable, nonatomic, strong) NSString * formSegueIdentifier;
@property (nullable, nonatomic, strong) Class formSegueClass;

@end

NS_ASSUME_NONNULL_END
